import { get, merge, set } from 'lodash-es'
import {
  Action,
  getModule,
  Module,
  Mutation,
  VuexModule
} from 'vuex-module-decorators'

import { getBaseInfo, loginByAccount, logout } from '@/api/sys/auth'
import type { AuthInfo, LoginParams } from '@/api/sys/model/authModel'
import type { AuthUserInfo, UserInfo } from '@/api/sys/model/userModel'
import { getUserInfo } from '@/api/sys/user'
import { currentPageMatch, useGlobalSetting } from '@/settings'
import { hasCacheA } from '@/store/plugins'
import { toPromise } from '@/utils'

import store from '../instance'
import { appStore } from './app'
import { ossStore } from './oss'

interface UserState {
  /* 登录token */
  readonly authInfo: MaybeNull<AuthInfo>

  /* 用户基础信息 */
  readonly authUserInfo: MaybeNull<AuthUserInfo>

  /* 当前小程序的用户信息 */
  readonly userInfo: MaybeNull<AnyObject>

  /* 获取登录token */
  readonly getToken: string

  /* 获取默认租户 */
  readonly getLoginTenantId: string

  /* 是否已登录 */
  readonly hasLogin: boolean
}

@Module({
  namespaced: true,
  name: 'user',
  dynamic: true,
  store,
  preserveState: hasCacheA('user')
})
class User extends VuexModule implements UserState {
  private _authInfo: MaybeNull<AuthInfo> = null
  private _authUserInfo: MaybeNull<AuthUserInfo> = null
  private _hasLogin = false
  private _lastUpdateTime = 0

  private _userInfo: MaybeNull<UserInfo> = null

  get authInfo() {
    return this._authInfo
  }

  get getToken() {
    return this._authInfo?.token ?? ''
  }

  get getLoginTenantId() {
    return this._authInfo?.tenantId ?? ''
  }

  get authUserInfo() {
    return this._authUserInfo as NonNullable<AuthUserInfo>
  }

  get userInfo() {
    return this._userInfo
  }

  get hasLogin(): boolean {
    return this._hasLogin
  }

  @Mutation
  setAuthInfo(val: AuthInfo): void {
    this._authInfo = val
  }

  @Mutation
  setAuthUserInfo(val: AuthUserInfo): void {
    this._authUserInfo = val
  }

  @Mutation
  setUserInfo(val: UserInfo): void {
    this._userInfo = val
  }

  @Mutation
  setHasLogin(val = true): void {
    this._hasLogin = val
  }

  @Mutation
  setLastUpdateTime(): void {
    this._lastUpdateTime = Date.now()
  }

  @Mutation
  $resetState() {
    this._authInfo = null
    this._authUserInfo = null
    this._userInfo = null
    this._lastUpdateTime = 0
    this._hasLogin = false
  }

  @Action
  async Login(params?: LoginParams) {
    const { wxAppId, checkAuth, appCode } = useGlobalSetting()

    let token = ''

    // 合并默认参数
    params = merge(
      {
        appCode,
        loginType: 2,
        thirdLoginReq: { thirdAppType: 1, miniAppId: wxAppId }
      },
      params
    )

    const isRefreshTokenByTenant = params?.loginType === 3

    const isQyWxLogin = get(params, 'thirdLoginReq.thirdAppType') === 2

    if (!isRefreshTokenByTenant) {
      const { code } = await toPromise(
        !isQyWxLogin ? uni.login : (wx as AnyObject).qy.login
      )
      set(params, 'thirdLoginReq.code', code)
    } else {
      token = this.getToken
      set(params, 'tenantId', params.tenantId || appStore.tenantId)
    }

    // const result = await loginByAccount(params, token)
    //     this.setAuthInfo({}//result
    //       as AuthInfo
    // )

    // 当账号密码登录时，设置用户为已登录状态
    if (!checkAuth || params?.userNameLoginReq) {
      this.setHasLogin(true)
    }

    if (this.authInfo?.tokenType === 1) {
      return this.afterLogin(true)
    }
    return {} as AuthUserInfo
  }

  @Action
  async afterLogin(isRest = false) {
    const checkExpireTime = Date.now() - this._lastUpdateTime > 24 * 3600

    if (checkExpireTime || !this.userInfo || isRest) {
      appStore.requestMyAppList().catch(console.error)

      return this.getAuthUserInfo()
    } else {
      return this.authUserInfo
    }
  }

  @Action
  async Logout() {
    // if (this.getToken) {
    //   try {
    //     await logout()
    //   } catch (e) {
    //     console.warn('登出失败', e)
    //   }
    // }

    this.$resetState()
    ossStore.$resetState()
    appStore.$resetState()

    // const { checkAuth } = useGlobalSetting()
    // checkAuth &&
    //   !currentPageMatch() &&
    uni.reLaunch({ url: '/pages/identity/login' })
  }

  @Action
  async getAuthUserInfo() {
    const baseInfo = await getBaseInfo()
    this.setAuthUserInfo(baseInfo)
    this.setLastUpdateTime()
    return baseInfo
  }

  @Action
  async requestUserInfo() {
    const userInfo = await getUserInfo()
    this.setUserInfo(userInfo)
    return userInfo
  }
}

export const userStore = getModule<User>(User)
